package com.wmx.thymeleafapp.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * Java jdk 原生 Des 加解密
 * Data Encrytion Standard（数据加密标准) , 特点：1. 对称加密  2. 同一个 SECRET_KEY（密钥）
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2024/4/13 11:10
 */
public class DesUtil {
    // 加密算法：可用 DES,DESede,Blowfish
    private static final String Algorithm = "DESede";
    private static final String CHARSET_UTF8 = "utf-8";
    // keySize must be equal to 112 or 168
    private static final int KEY_SIZE = 168;
    private static final Logger log = LoggerFactory.getLogger(DesUtil.class);

    /**
     * 生成密钥文本 - 保存记录起来（在配置文件、或者数据库中），用于后续进行加解密使用。
     *
     * @param keySrc ：用于生成密钥的内容，可以任意随机
     * @return ：返回密钥文本，如 SMtnONQhBBRiDWRS4GHn0z7mX9DFMl3LWexekXf9pRo=
     * @throws Exception
     */
    public static String generateKey(String keySrc) throws Exception {
        if (keySrc == null || keySrc.trim().isEmpty()) {
            keySrc = String.valueOf(System.currentTimeMillis());
        }
        KeyGenerator keyGen = KeyGenerator.getInstance(Algorithm);
        SecureRandom random = new SecureRandom(keySrc.getBytes(CHARSET_UTF8));
        keyGen.init(KEY_SIZE, random);
        SecretKey secretKey = keyGen.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * des 加密
     *
     * @param content       ：被加密的内容
     * @param secretKeyText ：密钥文本
     * @return ：加密好的内容(base64)
     */
    public static String encrypt(String content, String secretKeyText) throws Exception {
        SecretKey secretKey = strKeyToSecretKey(secretKeyText);
        byte[] src = content.getBytes(CHARSET_UTF8);
        byte[] encryptMode = encryptMode(secretKey, src);
        return Base64.getEncoder().encodeToString(encryptMode);
    }

    /**
     * DES 解密
     *
     * @param cipherText    ：密文(base64)
     * @param secretKeyText ：密钥
     * @return ：解密好的内容
     * @throws Exception
     */
    public static String decrypt(String cipherText, String secretKeyText) throws Exception {
        SecretKey secretKey = strKeyToSecretKey(secretKeyText);
        byte[] decode = Base64.getDecoder().decode(cipherText);
        byte[] bytes = decryptMode(secretKey, decode);
        return new String(bytes, CHARSET_UTF8);
    }

    /**
     * 生成密钥对象 - 用于根据密钥文本创建密钥对象进行数据加解密。
     *
     * @param strKey ：密钥文本
     * @return ：密钥对象
     */
    private static SecretKey strKeyToSecretKey(String strKey) {
        byte[] bytes = Base64.getDecoder().decode(strKey);
        SecretKeySpec secretKey = new SecretKeySpec(bytes, Algorithm);
        return secretKey;
    }

    /**
     * des 加密
     *
     * @param secretKey : 密钥
     * @param src       ：待加密的内容
     * @return ：加密好的数据
     * @throws Exception
     */
    private static byte[] encryptMode(SecretKey secretKey, byte[] src) throws Exception {
        Cipher cipher = Cipher.getInstance(Algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] enc = cipher.doFinal(src);
        return enc;
    }

    /**
     * des 解密
     *
     * @param secretKey 密钥
     * @param src       解密对象
     * @return
     * @throws Exception
     */
    private static byte[] decryptMode(SecretKey secretKey, byte[] src) throws Exception {
        Cipher cipher = Cipher.getInstance(Algorithm);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] dec = cipher.doFinal(src);
        return dec;
    }

    public static void main(String[] args) throws Exception {
        String data = "AES: Advanced Encrytion Standard（高级加密标准），特点：1. 对称加密  2. 一个 SECRET_KEY（密钥）扩展成多个子 SK，轮加密";
        String keySrc = "e27568c9-658c-49ea-b178-1437fce69046";
        String secretKeyText = DesUtil.generateKey(keySrc);
        // 密钥文本-> SctnONUgBBViDWRS4GHm0z7mXtDEMl3L
        System.err.println("密钥文本-> " + secretKeyText);

        String encrypt = DesUtil.encrypt(data, secretKeyText);
        // 密文-> Y9U3QYAzLSOxJryjvywBOsb+pDnGVnBoJ6gQwrPI+NFxyWWd3/shTFmI19gFuzHw7aHPSxM93I8Inz6SLtFb+ttjA/IhOs+Ug6ZP00wcZfKJT1nTMZ5PAJ+S0xa02WFJlz7SM3F/82mu/JYNbmd36b/xJjN1EkXe6EJjJbbGwJHrFxDR4BsfV5ky98Z/WFGSdbGPw0Quic4=
        System.out.println("密文-> " + encrypt);

        String decrypt = DesUtil.decrypt(encrypt, secretKeyText);
        System.out.println("明文-> " + decrypt);
    }
}